import { useAuthStore } from '@/stores/auth';
import { createRouter, createWebHashHistory, type RouteLocationNormalized, type RouteRecordRaw } from 'vue-router';
import { useTabStore, type OpenedTab } from '@/stores/tab';
import { storeToRefs } from 'pinia';
import { ElMessage } from 'element-plus';
import { SysMenuMode } from '@/entity/SysMenuMode';
import { ref } from 'vue';
import type { SysMenu } from '@/entity/SysMenu';

import SiderNavLayoutVue from "@/layout/SiderNavLayout.vue";
import IFrameViewVue from '@/views/IFrameView.vue';

import LoginVue from "@/views/Login.vue";

import WelcomeVue from "@/views/Welcome.vue";

import ProfileVue from '@/views/profile/Profile.vue';
import ChangePasswordVue from '@/views/profile/ChangePassword.vue';

import MessageCenterVue from '@/views/message-center/MessageCenter.vue';

import ApiResourceListVue from '@/views/system/api-resource/ApiResourceList.vue';
import DepartmentListVue from '@/views/system/department/DepartmentList.vue';
import MenuListVue from '@/views/system/menu/MenuList.vue';
import PositionListVue from '@/views/system/position/PositionList.vue';
import RoleListVue from '@/views/system/role/RoleList.vue';
import RoleDetailVue from '@/views/system/role/RoleDetail.vue';
import UserListVue from '@/views/system/user/UserList.vue';
import UserDetailVue from '@/views/system/user/UserDetail.vue';
import NoticeListVue from '@/views/system/notice/NoticeList.vue';

import OnlineUserListVue from '@/views/monitor/online-user/OnlineUserList.vue';
import MessageListVue from '@/views/monitor/message/MessageList.vue';
import LoginLogListVue from '@/views/monitor/login-log/LoginLogList.vue';
import OperationLogListVue from '@/views/monitor/operation-log/OperationLogList.vue';
import ServerVue from '@/views/monitor/server/Server.vue';

const IFRAME_VIEW_ROUTE_PATH = "/iframe";
const LOGIN_ROUTE_PATH = "/login";

const routes: RouteRecordRaw[] = [
  {
    path: "/",
    redirect: "/home",
  },
  {
    path: "/home",
    name: "Home",
    component: SiderNavLayoutVue,
    redirect: "/welcome",
    children: [
      {
        path: "/welcome",
        component: WelcomeVue,
      },
      {
        path: "/api-resource",
        component: ApiResourceListVue,
      },
      {
        path: "/department",
        component: DepartmentListVue,
      },
      {
        path: "/login-log",
        component: LoginLogListVue,
      },
      {
        path: "/menu",
        component: MenuListVue,
      },
      {
        path: "/online-user",
        component: OnlineUserListVue,
      },
      {
        path: "/operation-log",
        component: OperationLogListVue,
      },
      {
        path: "/position",
        component: PositionListVue,
      },
      {
        path: "/role",
        component: RoleListVue,
      },
      {
        path: "/role-detail",
        component: RoleDetailVue,
      },
      {
        path: "/message",
        component: MessageListVue,
      },
      {
        path: "/server",
        component: ServerVue,
      },
      {
        path: "/notice",
        component: NoticeListVue,
      },
      {
        path: "/user",
        component: UserListVue,
      },
      {
        path: "/user-detail",
        component: UserDetailVue,
      },
      {
        path: "/profile",
        component: ProfileVue,
      },
      {
        path: "/change-password",
        component: ChangePasswordVue,
      },
      {
        path: "/message-center",
        component: MessageCenterVue,
      },
      {
        path: IFRAME_VIEW_ROUTE_PATH,
        component: IFrameViewVue,
      },
    ],
  },
  {
    path: LOGIN_ROUTE_PATH,
    component: LoginVue,
  },
];

const router = createRouter({
  history: createWebHashHistory(import.meta.env.BASE_URL),
  routes: routes,
})

const whiteList = [
  LOGIN_ROUTE_PATH,
  IFRAME_VIEW_ROUTE_PATH,
];

/**
 * 异步路由是否已加载
 */
const asyncRoutesLoaded = ref(false);

/**
 * 加载异步路由
 */
const loadAsyncRoutes = async () => {
  const authStore = useAuthStore();
  // 登录成功后动态添加路由
  if (authStore.token) {
    const { userProfile } = storeToRefs(authStore);
    const menuList = userProfile?.value?.menuList || [];
    menuList.filter(it => it.mode == SysMenuMode.ASYNC_ROUTE).forEach(menu => {
      router.addRoute("Home", {
        path: menu.route,
        name: menu.code,
        component: () => import(/* @vite-ignore */menu.path),
        meta: {
          title: menu.name,
          icon: menu.icon,
        }
      });
    });
  }

  // 更新异步路由加载状态标志
  asyncRoutesLoaded.value = true;
}

/**
 * 路由守卫，路由跳转前
 */
router.beforeEach(async (to, from, next) => {
  const authStore = useAuthStore();
  // 如果用户已登录且目标路由是/login，直接跳转至首页
  if (authStore.token && to.path == LOGIN_ROUTE_PATH) {
    next("/");
    return;
  }

  // 如果是白名单路由则直接跳转
  if (whiteList.includes(to.path)) {
    next();
    return;
  }
  // 白名单之外所有路由都需要判断用户是否已登录，未登录则跳转至/login
  if (!authStore.token) {
    next({
      path: LOGIN_ROUTE_PATH
    });
  } else {
    // 已登录则判断异步路由是否已加载，若已加载完成则直接跳转
    if (!asyncRoutesLoaded.value) {
      // 异步路由未加载（通常是第一次登录或者页面刷新）时，首先加载异步路由
      await loadAsyncRoutes();
      next("/");
      return;
    }
    // 判断是否有打开路由的权限
    const authStore = useAuthStore();
    const { userProfile } = storeToRefs(authStore);
    const menuList = userProfile?.value?.menuList || [];
    const menu = menuList.find(it => it.route == to.path);
    if (menu != null) {
      next();
    } else {
      ElMessage.error("没有菜单权限");
      next(false);
    }
  }

});

/**
 * 路由守卫，路由跳转后
 */
router.afterEach(async (to, from) => {
  if (to.matched == null || to.matched.length < 1 || to.matched[0].path != "/home") {
    return;
  }
  // 在路由成功后需要记录已打开的tab页
  const tabStore = useTabStore();
  const authStore = useAuthStore();
  const { userProfile } = storeToRefs(authStore);
  const menuList = userProfile?.value?.menuList || [];
  if (to.path == IFRAME_VIEW_ROUTE_PATH) {
    const menuId = Number(to.query.menuId);
    const menu = menuList.find(it => it.id == menuId);
    if (menu != null) {
      openTab(to, menu, to.fullPath + "_" + new Date().getTime());
    }
    return;
  }
  const menu = menuList.find(it => it.route == to.path);
  if (menu != null) {
    openTab(to, menu);
  }
});

const openTab = async (to: RouteLocationNormalized, menu: SysMenu, tabId?: string, tabName?: string) => {
  const tabStore = useTabStore();

  const openedTab: OpenedTab = {
    tabId: to.fullPath,
    menuId: menu.id,
    tabName: menu.name,
    route: to,
  };
  tabStore.addTab(openedTab);
  tabStore.activeTabId = openedTab.tabId;
  tabStore.activeMenuId = openedTab.menuId;
}

export default router
